#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <linux/input.h>
#include <pthread.h>
#include <unistd.h>

#define BMP_MAX_NUMBER 4

char bmp_path[4][100] = {"1.1.bmp", "1.2.bmp", "1.3.bmp", "1.4.bmp"};
int slider_flag = 0;
pid_t pid;
pthread_mutex_t mutex;
pthread_cond_t cond;

int lcd_big_bmp(char *pathname, int x0, int y0,int mult_small_number)
{
	//1、打开设备文件
	int lcd = open("/dev/fb0", O_RDWR);
	if(-1 == lcd)
	{
		printf("lcd open error!\n");
		return -2;
	}
	
	//2、内存映射
	char *ptr =  (char *)mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, 
	                MAP_SHARED, lcd, 0);
	if(NULL == ptr)
	{
		printf("mmap error!\n");
		return -3;
	}
	//清除背景色
	//bzero(ptr, 800*480*4);
	
	//打开图片
	int bmp = open(pathname, O_RDWR);
	if(-1 == bmp)
	{
		printf("bmp open error!\n");
		return -2;
	}
	
	//读取图片相关信息
	int bmp_size, bmp_width, bmp_height;
	//大小
	lseek(bmp, 2, SEEK_SET);
	read(bmp, &bmp_size, sizeof(bmp_size));
	
	//宽度和高度
	lseek(bmp, 18, SEEK_SET);
	read(bmp, &bmp_width, sizeof(bmp_width));
	read(bmp, &bmp_height, sizeof(bmp_height));
	
	//读取图片的颜色数据
	lseek(bmp, 54, SEEK_SET);
	char *bmp_buf = malloc(bmp_size);	//申请空间
	read(bmp, bmp_buf, bmp_width*bmp_height*3);

	//假设不清楚图片的实际大小，那么就需要通过计算获取行和列需要缩小的倍数
	int mult_x, mult_y;
	mult_x = (bmp_width/801)+1;		//是为了确保得到1以上的结果，注意是整型
	mult_y = (bmp_height/481)+1;


	//获取最大的倍数
	
	//对颜色数据进行处理（上下颠倒以及数据混乱）
	int bmp_sum = 0;
	int lcd_y,bmp_y,lcd_sum = 0;
	int lcd_x, bmp_x;
	int i,j;
	
	for(lcd_y=0, bmp_y=0; lcd_y+y0<480 && bmp_y<bmp_height; lcd_y+=mult_small_number, bmp_y++)
	{
	  for(j=0;j<mult_small_number;j++)
	  	{
		//假设 mult_x = 3，那么每执行一次循环就会 加3 ，即x的数值为 0 3 6 9
		for(lcd_x=0, bmp_x=0; lcd_x+x0<600 && bmp_x<bmp_width; lcd_x+=mult_small_number, bmp_x++)
		{
		  for(i=0;i<mult_small_number;i++)
			{
			
			bmp_sum = 3*(bmp_x+((bmp_height-1-bmp_y)*bmp_width));
			lcd_sum = 4*(800*(lcd_y+j+y0)+lcd_x+i+x0);
			
			//等号的坐标属于lcd屏幕， 等号的右边是bmp图像数据
			ptr[lcd_sum+0] = bmp_buf[bmp_sum+0]; //蓝色数据
			ptr[lcd_sum+1] = bmp_buf[bmp_sum+1]; //绿色数据
			ptr[lcd_sum+2] = bmp_buf[bmp_sum+2]; //红色数据
			ptr[lcd_sum+3] = bmp_buf[bmp_sum+3]; //透明度数据
		  	}
		}
	  	}
		usleep(1);
	}
	munmap(ptr, 800*480*4);
	free(bmp_buf);
	//3、关闭文件
	close(lcd);
	close(bmp);
}

int lcd_small_bmp(char *pathname, int x0, int y0,int mult_small_number)
{
	//1、打开设备文件
	int lcd = open("/dev/fb0", O_RDWR);
	if(-1 == lcd)
	{
		printf("lcd open error!\n");
		return -2;
	}
	
	//2、内存映射
	char *ptr =  (char *)mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, 
	                MAP_SHARED, lcd, 0);
	if(NULL == ptr)
	{
		printf("mmap error!\n");
		return -3;
	}
	//清除背景色
	//bzero(ptr, 800*480*4);
	
	//打开图片
	int bmp = open(pathname, O_RDWR);
	if(-1 == bmp)
	{
		printf("bmp open error!\n");
		return -2;
	}
	
	//读取图片相关信息
	int bmp_size, bmp_width, bmp_height;
	//大小
	lseek(bmp, 2, SEEK_SET);
	read(bmp, &bmp_size, sizeof(bmp_size));
	
	//宽度和高度
	lseek(bmp, 18, SEEK_SET);
	read(bmp, &bmp_width, sizeof(bmp_width));
	read(bmp, &bmp_height, sizeof(bmp_height));
	
	//读取图片的颜色数据
	lseek(bmp, 54, SEEK_SET);
	char *bmp_buf = malloc(bmp_size);	//申请空间
	read(bmp, bmp_buf, bmp_width*bmp_height*3);

	//假设不清楚图片的实际大小，那么就需要通过计算获取行和列需要缩小的倍数
	int mult_x, mult_y;
	mult_x = (bmp_width/801)+1;		//是为了确保得到1以上的结果，注意是整型
	mult_y = (bmp_height/481)+1;

/*
	//获取最大的倍数
	if(mult_x > mult_y)
	{
		//mult_small_number = mult_x;
		mult_small_number = 4;
	}
	else 
	{
		//mult_small_number = mult_y;
		mult_small_number = 4;
	}
*/	
	//对颜色数据进行处理（上下颠倒以及数据混乱）
	int bmp_sum = 0;
	int lcd_y,bmp_y,lcd_sum = 0;
	int lcd_x, bmp_x;
	//int i,j;
	
	for(lcd_y=0, bmp_y=0; lcd_y+y0<480 && bmp_y<bmp_height; lcd_y++, bmp_y+=mult_small_number)
	{
		//假设 mult_x = 3，那么每执行一次循环就会 加3 ，即x的数值为 0 3 6 9
		for(lcd_x=0, bmp_x=0; lcd_x+x0<600 && bmp_x<bmp_width; lcd_x++, bmp_x+=mult_small_number)
		{
		  
			
			bmp_sum = 3*(bmp_x+((bmp_height-1-bmp_y)*bmp_width));
			lcd_sum = 4*(800*(lcd_y+y0)+lcd_x+x0);
			
			//等号的坐标属于lcd屏幕， 等号的右边是bmp图像数据
			ptr[lcd_sum+0] = bmp_buf[bmp_sum+0]; //蓝色数据
			ptr[lcd_sum+1] = bmp_buf[bmp_sum+1]; //绿色数据
			ptr[lcd_sum+2] = bmp_buf[bmp_sum+2]; //红色数据
			ptr[lcd_sum+3] = bmp_buf[bmp_sum+3]; //透明度数据
		  	
		}
	  	
		
	}
	munmap(ptr, 800*480*4);
	free(bmp_buf);
	//3、关闭文件
	close(lcd);
	close(bmp);
}

//自定义函数：LCD屏幕显示bmp图片
//pathname:需要打开的图片路径
//x0：存放图片显示的x轴起点
//y0：存放图片显示的y轴起点
int lcd_show_bmp(char *pathname, int x0, int y0)
{
	//1、打开设备文件
	int lcd = open("/dev/fb0", O_RDWR);
	if(-1 == lcd)
	{
		printf("lcd open error!\n");
		return -2;
	}
	
	//2、内存映射
	char *ptr =  (char *)mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, 
	                MAP_SHARED, lcd, 0);
	if(NULL == ptr)
	{
		printf("mmap error!\n");
		return -3;
	}
	//清除背景色
	//bzero(ptr, 800*480*4);
	
	//打开图片
	int bmp = open(pathname, O_RDWR);
	if(-1 == bmp)
	{
		printf("bmp open error!\n");
		return -2;
	}
	
	//读取图片相关信息
	int bmp_size, bmp_width, bmp_height;
	//大小
	lseek(bmp, 2, SEEK_SET);
	read(bmp, &bmp_size, sizeof(bmp_size));
	
	//宽度和高度
	lseek(bmp, 18, SEEK_SET);
	read(bmp, &bmp_width, sizeof(bmp_width));
	read(bmp, &bmp_height, sizeof(bmp_height));
	
	//读取图片的颜色数据
	lseek(bmp, 54, SEEK_SET);
	char *bmp_buf = malloc(bmp_size);	//申请空间
	read(bmp, bmp_buf, bmp_width*bmp_height*3);

	
	//对颜色数据进行处理（上下颠倒以及数据混乱）
	int bmp_sum = 0;
	int lcd_sum = 0;
	for(int y=0; y+y0<480 && y<bmp_height; y++)
	{
		for(int x=0; x+x0<800 && x<bmp_width; x++)
		{
			bmp_sum = 3*(x+((bmp_height-1-y)*bmp_width));
			lcd_sum = 4*(800*(y+y0)+x+x0);
			
			//等号的坐标属于lcd屏幕， 等号的右边是bmp图像数据
			ptr[lcd_sum+0] = bmp_buf[bmp_sum+0]; //蓝色数据
			ptr[lcd_sum+1] = bmp_buf[bmp_sum+1]; //绿色数据
			ptr[lcd_sum+2] = bmp_buf[bmp_sum+2]; //红色数据
			ptr[lcd_sum+3] = bmp_buf[bmp_sum+3]; //透明度数据
		}
		//usleep(1);
	}

	munmap(ptr, 800*480*4);
	free(bmp_buf);
	//3、关闭文件
	close(lcd);
	close(bmp);
}


int touch_flag = 1;
int ts_x, ts_y;
int old_x = 300;
int slider_left = 0;
int slider_right = 0;
int flag_x_y = 0;
int right_left_slide_flag = 0;
struct input_event ts;
int flag_x = 0, flag_y = 0, first_press_flag = 0;
//获取触摸屏坐标
//自定义函数：获取触摸屏的坐标
void get_touch()
{
    //1、打开设备文件
    int touch_fd = open("/dev/input/event0", O_RDONLY);
    if(-1 == touch_fd)
    {
        printf("event0 open error!\n");
    }

    while(1)
    {
        read(touch_fd, &ts, sizeof(ts));
	//3、分析数据
        if(EV_ABS == ts.type) //判断是否为触摸屏事件
        {
            if(ABS_X == ts.code)//判断是否为x轴数据
            {
                ts_x = ts.value;
                flag_x = 1;	
            }
            else if(ABS_Y == ts.code) //判断是否为y轴数据
            {
                ts_y = ts.value;
                flag_y = 1;
            }
        }

	if(EV_KEY == ts.type)
	{
		//刚触碰的坐标/长按时
		if(ts.code == BTN_TOUCH && ts.value == 1)
		{
			old_x = ts_x;
			first_press_flag = 1;
		}
	}
	
	if(flag_x == 1 && flag_y == 1 && first_press_flag == 1) 
        {
		flag_x = 0;
		flag_y = 0;
		pthread_mutex_lock(&mutex);
		flag_x_y = 1;  
		//黑色底板才需要执行如下操作
		ts_x = ts_x*800/1024;
		ts_y = ts_y*480/600; 
		pthread_mutex_unlock(&mutex);
		pthread_cond_signal(&cond);
		//break;                    
        }

        if(EV_KEY == ts.type)
	{
		//松开
		if(ts.code == BTN_TOUCH && ts.value == 0)
		{
			//从左到右的滑动
			if(((ts_x > old_x) && (ts_x - old_x > 150) && (ts_x < 600)))
			{
				right_left_slide_flag = 1;
				slider_right = 1;			
				old_x = 300;
			}	
			//从右到左的滑动
			else if(((old_x > ts_x) && (old_x - ts_x > 150) && (old_x < 600)))
			{
				
				right_left_slide_flag = 1;
				slider_left = 1;
				old_x = 300;
			}
		}
	}



    }
    //4、关闭文件
    close(touch_fd);
}

void *right_left_slide_func(void *arg)
{
	printf("enter right_left_slide_func\r\n");
	while(1){
		if(right_left_slide_flag == 1){
			if(slider_left == 1){
				touch_flag--;
				if(touch_flag <= 0)
					touch_flag = BMP_MAX_NUMBER;
				lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
				slider_left = 0;
				right_left_slide_flag == 0;
			}
			else if(slider_right == 1){
				touch_flag++;
				if(touch_flag > BMP_MAX_NUMBER)
					touch_flag = 1;
				lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
				slider_right = 0;
				right_left_slide_flag == 0;
			}
			right_left_slide_flag == 0;
		}	
	}
}

void *area_switch()
{
	printf("enter area_switch\r\n");
	while(1){
		pthread_mutex_lock(&mutex);

		while(flag_x_y == 0)
			pthread_cond_wait(&cond, &mutex);
		while(flag_x_y == 1){
			//上一张
			if((ts_y > 0 && ts_y < 120) && (ts_x > 600))
			{
				touch_flag--;
				if(touch_flag <= 0)
					touch_flag = BMP_MAX_NUMBER;
		
				lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
				ts_x = 0;
				ts_y = 0;
			}
			//发送命令回到主界面
			else if((ts_y > 0 && ts_y < 100) && (ts_x > 0 && ts_y <100)){
				char temp2[30]; 
				char command2[30];
				int pid = getpid();
				sprintf(temp2, "%d", pid);
				sprintf(command2, "kill -9 %s", temp2);

				int fd = open("/tmp/lcdpipe", O_RDWR);
				char send_buf[100] = "cd /mnt/udisk && ./mainWindowApp";
				write(fd, send_buf, sizeof(send_buf));
				printf("send message\r\n");
				system(command2);
			}
			//下一张
			else if((ts_y > 120 && ts_y < 240) && (ts_x > 600))
			{
				touch_flag++;
				if(touch_flag > BMP_MAX_NUMBER)
					touch_flag = 1;
		
				lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
				ts_x = 0;
				ts_y = 0;
			}
			else if((ts_y > 400 && ts_y < 480) && (ts_x > 0 && ts_x < 200))
			{

				lcd_big_bmp(bmp_path[touch_flag - 1], 0, 0, 3);
				
				ts_x = 0;
				ts_y = 0;
			}
			else if((ts_y > 400 && ts_y < 480) && (ts_x > 300 && ts_x < 500))
			{
				lcd_show_bmp("temp_black.bmp", 0, 0);
				lcd_small_bmp(bmp_path[touch_flag - 1], 0, 0, 3);
				old_x = 300;
				ts_x = 300;
				ts_y = 0;
			}
			//幻灯片
			else if((ts_y > 240 && ts_y < 360) && (ts_x > 600))
			{
				printf("click slider photo\r\n");
				if(slider_flag == 0){
					slider_flag = 1;
				}
				else{
					slider_flag = 0;
				}
				printf("slider_flag = %d\r\n", slider_flag);
				ts_x = 0;
				ts_y = 0;
			}
			//息屏
			else if((ts_y > 360 && ts_y < 480) && (ts_x > 600))
			{
				char command[] = "kill -9 ";
				char str[10];
				sprintf(str, "%d", pid);
				strcat(command, str);
				printf("command = %s\r\n", command);
				//方式一：显示一张黑色的图片
				lcd_show_bmp("black.bmp", 0, 0);
				system(command);
			}
			else{
				flag_x_y = 0;
				break;
			}
			flag_x_y = 0;
		}

		pthread_mutex_unlock(&mutex);
	}
	
}


void *slider_func(void *arg)
{
	printf("enter slider_func : %d\r\n", pthread_self());
	while(1){
		if(slider_flag == 1){
			printf("enter slider_func\r\n");
			touch_flag++;
			if(touch_flag > BMP_MAX_NUMBER)
				touch_flag = 1;
			lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
			sleep(1);
		}
	}
}


int main()
{
	int ret = mkfifo("/tmp/lcdpipe", 0777);
	if(ret < 0){
		perror("!!mkfifo!!");
	}

	lcd_show_bmp("choice.bmp", 600, 0);
	lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
	if(fork() == 0){
		//通过管道来接收要执行程序命令，然后执行
		char rec_buf[100];
		int fd = open("/tmp/lcdpipe", O_RDWR);
		read(fd, rec_buf, sizeof(rec_buf));
		printf("receive message\r\n");
		system(rec_buf);
	}
	
	else{
		pthread_t tid, tid_area_switch, tid_right_left_slide;
		int ret = 0;
	
		pthread_create(&tid, NULL, slider_func, NULL);
		pthread_create(&tid_area_switch, NULL, area_switch, NULL);
		pthread_create(&tid_right_left_slide, NULL, right_left_slide_func, NULL);

		pthread_mutex_init(&mutex, NULL);
		pthread_cond_init(&cond, NULL);
	
		printf("main thread = %ld\r\n", pthread_self());
		pid = getpid();
		printf("pid = %d\r\n", pid);

		while(1){
			get_touch();
		}
	
		pthread_join(tid, NULL);
		pthread_join(tid_area_switch, NULL);
		pthread_join(tid_right_left_slide, NULL);
		pthread_cond_destroy(&cond);
		exit(0);
	}


}



